<?php
namespace FastPHP\Core;

class ErrorHandler
{
    protected static $debug = true;
    protected static $logFile = '';

    public static function register()
    {
        $config = require APP_PATH . 'config/app.php';
        self::$debug = !empty($config['debug']);
        self::$logFile = APP_PATH . 'runtime/error.log';
        set_exception_handler([self::class, 'handleException']);
        set_error_handler([self::class, 'handleError']);
        register_shutdown_function([self::class, 'handleShutdown']);
    }

    public static function handleException($e)
    {
        self::logError($e);
        self::renderError($e->getMessage(), $e->getCode() ?: 500, $e);
    }

    public static function handleError($errno, $errstr, $errfile, $errline)
    {
        $msg = "[$errno] $errstr in $errfile on line $errline";
        self::logError($msg);
        // 转为ErrorException抛出，便于统一处理
        throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
    }

    public static function handleShutdown()
    {
        $error = error_get_last();
        if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
            $msg = "[{$error['type']}] {$error['message']} in {$error['file']} on line {$error['line']}";
            self::logError($msg);
            self::renderError($msg, 500);
        }
    }

    protected static function renderError($message, $code = 500, $exception = null)
    {
        http_response_code($code);
        $msg = $message;
        $debug = self::$debug;
        $trace = $exception ? $exception->getTraceAsString() : '';
        include APP_PATH . 'FastPHP/tpl/error.php';
        exit;
    }

    protected static function logError($error)
    {
        if (!is_dir(APP_PATH . 'runtime')) {
            mkdir(APP_PATH . 'runtime', 0777, true);
        }
        $date = date('Y-m-d H:i:s');
        if ($error instanceof \Throwable) {
            $msg = "[$date] " . get_class($error) . ': ' . $error->getMessage() . " in " . $error->getFile() . " on line " . $error->getLine() . "\n" . $error->getTraceAsString() . "\n";
        } else {
            $msg = "[$date] $error\n";
        }
        file_put_contents(self::$logFile, $msg, FILE_APPEND);
    }
} 